#include "theater.h"
#include "synch.h"
#include "system.h"

//the manager told the ticketTaker to work
void ticketTaker_startWork(unsigned int tictaker_workno)
{
    DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
    while(1)
    {
        //STEP 1: check the manager ask me to take the ticket or not
        /*      ticTkrReadyLock[tictaker_workno]->Acquire();
              if(NOTREADYTOTAKETIC==ticTkr_ready[tictaker_workno])
                  ticTkrReady_cv[tictaker_workno]->Wait(ticTkrReadyLock[tictaker_workno]);
               ticTkrReadyLock[tictaker_workno]->Release();*/
        //if the movie is now playing, nobody could enter the room, wait until the movie technicial signal me

check:
        DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
        ticketTakerMsgLock[tictaker_workno]->Acquire();
        DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
        if(OFF_WORK==ticketTaker_off[tictaker_workno]||NOTREADYTOTAKETIC==ticTkr_ready)//the ticket clerk only work
            //when ticketTaker_off = on_work, movie is not playing and the manager tol to take ticket
        {
            DBGPRINT(DEBUG_INFO, "tictaker_workno %d, ticketTaker_off:%d,ticTkr_ready%d ticketTaker_cus_count[tictaker_workno] %d \n ", tictaker_workno,ticketTaker_off[tictaker_workno],ticTkr_ready,ticketTaker_cus_count[tictaker_workno]);
            if(ticketTaker_cus_count[tictaker_workno]>0&&OFF_WORK==ticketTaker_off[tictaker_workno])//if the clerk is off, should ask people to take another line
            {
                DBGPRINT(DEBUG_INFO, "the ticket taker %d is break, i need to tell  the customers \n ", tictaker_workno);
				printf("TicketTaker [%d] is going on break.\n", tictaker_workno);
                ticketTakerline_cv[tictaker_workno]->Broadcast(ticketTakerLineLock);
                DBGPRINT(DEBUG_INFO, "tictaker_workno %d, ticketTaker_off:%d,ticTkr_ready%d ticketTaker_cus_count[tictaker_workno] %d \n ", tictaker_workno,ticketTaker_off[tictaker_workno],ticTkr_ready,ticketTaker_cus_count[tictaker_workno]);
                ticketTakerLineLock->Acquire();
                DBGPRINT(DEBUG_INFO, "tictaker_workno %d, ticketTaker_off:%d,ticTkr_ready%d ticketTaker_cus_count[tictaker_workno] %d \n ", tictaker_workno,ticketTaker_off[tictaker_workno],ticTkr_ready,ticketTaker_cus_count[tictaker_workno]);
                ticketTaker_cus_count[tictaker_workno]=0;
                DBGPRINT(DEBUG_INFO, "tictaker_workno %d, ticketTaker_off:%d,ticTkr_ready%d ticketTaker_cus_count[tictaker_workno] %d \n ", tictaker_workno,ticketTaker_off[tictaker_workno],ticTkr_ready,ticketTaker_cus_count[tictaker_workno]);
                ticketTakerLineLock->Release();
            }
            DBGPRINT(DEBUG_INFO, "tictaker_workno %d, ticketTaker_off:%d,ticTkr_ready%d ticketTaker_cus_count[tictaker_workno] %d \n ", tictaker_workno,ticketTaker_off[tictaker_workno],ticTkr_ready,ticketTaker_cus_count[tictaker_workno]);
            ticketTaker_state[tictaker_workno]=0;
            ticketTakerMsg_cv[tictaker_workno]->Wait(ticketTakerMsgLock[tictaker_workno]);
            ticketTakerMsgLock[tictaker_workno]->Release();
            DBGPRINT(DEBUG_INFO, "the ticket taker %d is waked up, I need to check what happened \n ", tictaker_workno);
			printf("TicketTaker [%d] is coming off break.\n", tictaker_workno);
            goto check;
        }
        DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);


        if(ticketTaker_cus_count[tictaker_workno]==0) //if no one is in the line
        {
			printf("TicketTaker [%d] has no one in line. I am available for a customer.\n", tictaker_workno);
			ticketTakerMsg_cv[tictaker_workno]->Wait(ticketTakerMsgLock[tictaker_workno]);
        }
		else//if some one was waiting
		{
			ticketTakerLineLock->Acquire();// to get the lock of the line
			ticketTakerline_cv[tictaker_workno]->Signal(ticketTakerLineLock);
			ticketTakerLineLock->Release();
			ticketTakerMsg_cv[tictaker_workno]->Wait(ticketTakerMsgLock[tictaker_workno]);
		}
		
        //step 2: wait for the customer to check how many the customers want to enter, and add to the total
        DBGPRINT(DEBUG_INFO,"ticket clerk %d is waiting for the customer to give tickets\n", tictaker_workno);
        DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d, ticTkr_ready %d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno],ticTkr_ready);
        
        DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d tictaker_tic_number[tictaker_workno] %d  ticketTaker_off[tictaker_workno] %d %d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno],tictaker_tic_number[tictaker_workno],ticketTaker_off[tictaker_workno],ticTkr_ready);
        //right here, we need to check i am waked up by the customer to buy or the manager to break
        if(tictaker_tic_number[tictaker_workno]==0||OFF_WORK==ticketTaker_off[tictaker_workno]|| NOTREADYTOTAKETIC==ticTkr_ready||ticketTaker_cus_count[tictaker_workno]==0)
            {
                DBGPRINT(DEBUG_INFO,"tictaker_workno %d are waked up but not by the customers\n", tictaker_workno);
                ticketTakerMsgLock[tictaker_workno]->Release();
                goto check;
            }
		printf("TicketTaker [%d] has a line length [%d] and is signaling a customer.\n", tictaker_workno, ticketTaker_cus_count[tictaker_workno]);
        DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
        ticketTakerLineLock->Acquire();
        DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
        ticketTaker_state[tictaker_workno]=1;
        ticketTakerLineLock->Release();
        DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
        DBGPRINT(DEBUG_TRACE, "ticket taker has knows the customer wants %d tickets\n", tictaker_tic_number[tictaker_workno]);
		printf("TicketTaker [%d] has received [%d] tickets.\n", tictaker_workno, tictaker_tic_number[tictaker_workno]);
        //step 3: the ticket taker check out if there are enough seats for the group
        seatsRsvLock->Acquire();
        DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
        if((seatsReserved+tictaker_tic_number[tictaker_workno])<=SEATS_SIZE)//if there are enough seats
        {
			printf("TicketTaker [%d] is allowing the group into the theater. The number of tickets taken is [%d].\n", tictaker_workno, tictaker_tic_number[tictaker_workno]);
            ticketTakerLineLock->Acquire();
            ticketTaker_cus_count[tictaker_workno]--;
            ticketTakerLineLock->Release();
            seats_from[tictaker_workno]=seatsReserved;
            DBGPRINT(DEBUG_TRACE,"ticket taker %d ,seats_from[tictaker_workno]%d seats_to[tictaker_workno] %d\n",tictaker_workno,seats_to[tictaker_workno],seats_to[tictaker_workno]);
            seats_to[tictaker_workno]=seatsReserved+tictaker_tic_number[tictaker_workno];
            DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
            seatsReserved+=tictaker_tic_number[tictaker_workno];
            totalCustomerEnteredLock->Acquire();
            DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
            totalCustomerEntered+=tictaker_tic_number[tictaker_workno];
            totalCustomerEnteredLock->Release();
            seats_result[tictaker_workno]=SEATS_GOT;
            //step 4:tell the customer which room they should go to
            room_number[tictaker_workno]=ROOM_NUM;
            DBGPRINT(DEBUG_TRACE, "ticket taker %d tell customer sit from %d to %d in room %d\n",tictaker_workno,seats_from[tictaker_workno],seats_to[tictaker_workno],room_number[tictaker_workno]);
            if(totalCustomer==totalCustomerEntered)//that means these are the last customers, we should give them movie
            {
                DBGPRINT(DEBUG_TRACE, "ticket taker %d find they are the last customers, we have %d today\n",tictaker_workno,totalCustomerEntered);

                roomfullLock->Acquire();
                DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
                //right here, we print all the things

                RoomFull=ROOMFULL;//the room is full, tell the movei technician that he could start the movie
                roomfullLock->Release();
                DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
                movieTechMsgLock->Acquire();
                DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
                movieTechMsg_cv->Signal(movieTechMsgLock);
                DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
                movieTechMsgLock->Release();
                DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
            }
        }
        else
        {
			printf("TicketTaker [%d] is not allowing the group into the theater. The number of taken tickets is [%d] and the group size is [%d].\n", tictaker_workno, tictaker_tic_number[tictaker_workno], ticketTaker_cus_count[tictaker_workno]);
            DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
            DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
            DBGPRINT(DEBUG_TRACE, "ticket taker %d tell customer should wait\n",tictaker_workno);
            seats_result[tictaker_workno]=SEATS_FAILED;
            //  seats_from[tictaker_workno]=seatsReserved;
            //   seats_to[tictaker_workno]=seatsReserved;// set these two the same, so the customer need to wait for another
            DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);

            roomfullLock->Acquire();
            DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
            RoomFull=ROOMFULL;//the room is full, tell the movei technician that he could start the movie
            DBGPRINT(DEBUG_TRACE, "ticket taker %d tell movie Technician room is full now\n",tictaker_workno);
            roomfullLock->Release();
            movieTechMsgLock->Acquire();
            DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
            movieTechMsg_cv->Signal(movieTechMsgLock);
            DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
            movieTechMsgLock->Release();
            DBGPRINT(DEBUG_TRACE,"ticket taker %d is going to work, customer no%d\n",tictaker_workno,ticketTaker_cus_count[tictaker_workno]);
        }
        seatsRsvLock->Release();
        //wake up by the customer and let them go to the room
        DBGPRINT(DEBUG_TRACE,"ticket taker %d ,seats_from[tictaker_workno]%d seats_to[tictaker_workno] %d\n",tictaker_workno,seats_to[tictaker_workno],seats_to[tictaker_workno]);
        tictaker_tic_number[tictaker_workno]=0;
        ticketTakerMsg_cv[tictaker_workno]->Signal(ticketTakerMsgLock[tictaker_workno]);
        DBGPRINT(DEBUG_TRACE,"ticket taker %d ,seats_from[tictaker_workno]%d seats_to[tictaker_workno] %d\n",tictaker_workno,seats_to[tictaker_workno],seats_to[tictaker_workno]);
        ticketTakerMsgLock[tictaker_workno]->Release();
        DBGPRINT(DEBUG_TRACE, "%d customers buy, %d customer entered,RoomFull %d\n",totalCustomer,totalCustomerEntered,RoomFull);
    }
};



